Run in Google Colab
|
!pip install -q https://github.com/pandas-profiling/pandas-profiling/archive/master.zip
# Librería para hacer requests
import requests
# Librerías para manejo de archivos
import os
import zipfile
import sys
# Librería para experiencia de usuario
from tqdm import tqdm
# Librerías para manejo de datos
import numpy as np
import pandas as pd
# Librerías para gráficas
import matplotlib.pyplot as plt
import seaborn as sns
plt.style.use("ggplot")
# Librerías para análisis de datos.
from scipy import stats
import pandas_profiling
url = "https://archive.ics.uci.edu/ml/machine-learning-databases/00222/bank-additional.zip"
def download_content(url, chnksz=1000, filename="image.jpg", zip=False):
"""
Función que se encarga de descargar un archivo deseado
:param url: la url de descarga
:param filename: El nombre del archivo
:param zip: Boolean que indica si lo que se descarga
es zipfile
"""
try:
r = requests.get(url)
except Exception as e:
print("Error de conexión con el servidor")
sys.exit()
with open(filename, "wb") as f:
bar = tqdm(
unit="KB",
desc="Descargando archivos",
total=int(
np.ceil(int(r.headers["content-length"])/chnksz)
)
)
for pkg in r.iter_content(chunk_size=chnksz):
f.write(pkg)
bar.update(int(len(pkg)/chnksz))
bar.close()
if zip:
with zipfile.ZipFile(filename, "r") as zfile:
print("\nExtrayedo Zip File...")
zfile.extractall()
print("Eliminando Zip File...")
os.remove(filename)
return
def null_percentage(df, int_mode=False):
"""
Función encargada de calcular los porcentajes de nulidad
de cada columna del dataframe
:param df: el dataframe
:param int_mode: boolean que pregunta si la salida es
numérica
:return: un diccionario con los porcentajes por columna.
"""
null_percentages = dict()
for col in df.columns:
percentage = df[col].isna().sum() * 100
percentage /= df.shape[0]
if not int_mode:
percentage = f"{percentage}% of null values"
null_percentages[col] = percentage
return null_percentages
def drop_null_column(df, drop_perc=85):
"""
Función que se encarga de borrar las columnas con
un porcentaje de nulidad mayor al 85
:param df: el dataframe
:return: el dataframe limpio
"""
null_perc = null_percentage(df, int_mode=True)
for col in df.columns:
if null_perc[col] > drop_perc:
df.drop(columns=col, inplace=True)
def change_dtypes(df):
"""
Función que se encarga de verificar los tipos de
datos del dataset y los convierte a categóricos, int16
o float 16
:param df: Dataset al cual se le ajustarán los datos
"""
for idx, dtype in zip(df.dtypes.index, df.dtypes.values):
try:
if dtype == "object":
df[idx] = df[idx].astype("category")
elif dtype == "int64":
df[idx] = df[idx].astype("int16")
elif dtype == "float64":
df[idx] = df[idx].astype("float16")
except Exception as e:
print(e)
continue
def get_cross_tab(index, columns):
"""
Función que se encarga de calcular la tabla de valores
cruzados
:param index: El índice de la tabla
:param columns: Las columnas de la tabla
:return: La tabla indexada
"""
table = pd.crosstab(index=index, columns=columns, margins=True)
table.index = [*table.index[:-1], f"total {index.name}"]
table.columns = [*table.columns[:-1], f"total {columns.name}"]
return table
def chi2test(table, ci=0.95):
"""
Función encargada de hacer la prueba de Chi2
para variables categóricas.
:param table: La tabla de variables
:param ci: el intervalo de confianza
"""
_, p_value, _, _ = stats.chi2_contingency(table)
print(f"Prueba de Chi2 con intervalo de confianza: {ci}")
print(f"El p-value equivale a: {p_value}")
alpha = 1. - ci
if p_value <= alpha:
print("Se rechaza la H0")
else:
print("No hay pruebas suficientes para rechazar H0")
download_content(url, filename="file.zip", zip=True)
data = pd.read_csv("./bank-additional/bank-additional-full.csv", delimiter=";",
na_values=["unknown"])
data.head()
pandas_profiling.ProfileReport(data)
Tomado de https://archive.ics.uci.edu/ml/datasets/bank+marketing
data.head()
object, sería bueno si cambiamos esos datos a category, igualmente con los int64 para int16 y los float64 a float16.data.dtypes
change_dtypes(data)
data.dtypes
data[data.duplicated()]
{'age': '0.0% of null values',
'campaign': '0.0% of null values',
'cons.conf.idx': '0.0% of null values',
'cons.price.idx': '0.0% of null values',
'contact': '0.0% of null values',
'day_of_week': '0.0% of null values',
'default': '20.872584247839175% of null values',
'duration': '0.0% of null values',
'education': '4.202680392347285% of null values',
'emp.var.rate': '0.0% of null values',
'euribor3m': '0.0% of null values',
'housing': '2.40361270272895% of null values',
'job': '0.8012042342429834% of null values',
'loan': '2.40361270272895% of null values',
'marital': '0.1942313295134505% of null values',
'month': '0.0% of null values',
'nr.employed': '0.0% of null values',
'pdays': '0.0% of null values',
'poutcome': '0.0% of null values',
'previous': '0.0% of null values',
'y': '0.0% of null values'}
data.dropna(thresh=19, inplace=True)
for idx, val in zip(data.dtypes.index, data.dtypes.values):
if val.name == "category":
print(f"Valores de {idx}: {data[idx].unique()}")
data["age"].unique()
table_marital = get_cross_tab(data["marital"], data["y"])
table_marital
# Frecuencias relativas totales
table_marital / table_marital.loc["total marital", "total y"]
# Frecuencias relativas a la columna
table_marital / table_marital.loc["total marital"]
# Frecuencias relativas a la variable
table_marital.div(table_marital["total y"], axis=0)
table_marital[["yes", "no"]].plot(kind="bar");
table_poutcome = get_cross_tab(data["poutcome"], data["y"])
# Frecuencias relativas totales
table_poutcome / table_poutcome.loc["total poutcome", "total y"]
# Frecuencias relativas a la columna
table_poutcome / table_poutcome.loc["total poutcome"]
# Frecuencias relativas a la variable
table_poutcome.div(table_poutcome["total y"], axis=0)
table_poutcome[["yes", "no"]].plot(kind="bar");
table_duration = (data.groupby("y").duration.agg(["mean", "std", "sem"])
.style.background_gradient(cmap="RdBu", axis=0))
table_duration
sns.violinplot(x="y", y="duration", data=data)
plt.ylabel("Duration (Seconds)")
plt.xlabel("Suscribed")
plt.show()
table_loan = get_cross_tab(data["loan"], data["y"])
# Frecuencias relativas totales
table_loan / table_loan.loc["total loan", "total y"]
# Frecuencias relativas a la columna
table_loan / table_loan.loc["total loan"]
# frecuencias relativas a la variable
table_loan.div(table_loan["total y"], axis=0)
table_loan[["yes", "no"]].plot(kind="bar")
data["y_num"] = (data["y"] == "yes").astype("int")
data[["duration", "y_num"]].corr(method="pearson")
crosstab = pd.crosstab(index=data["loan"], columns=data["y"])
chi2test(crosstab, 0.95)